package org.nkumar.immortal.web;

import junit.framework.TestCase;

import static org.easymock.EasyMock.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import java.io.IOException;

//TODO add tests for gzip
public final class ImmortalFilterTest extends TestCase
{
    public void testNotGetHeadMethod() throws IOException, ServletException
    {
        methodTest("POST");
        methodTest("PUT");
        methodTest("DELETE");
        methodTest("XYZ");
    }

    private static void methodTest(String method)
            throws IOException, ServletException
    {
        final ImmortalFilter filter = new ImmortalFilter();
        final HttpServletRequest request = createMock(HttpServletRequest.class);
        final HttpServletResponse response = createMock(HttpServletResponse.class);
        final FilterChain filterChain = createMock(FilterChain.class);
        expect(request.getMethod()).andReturn(method);
        response.sendError(eq(HttpServletResponse.SC_METHOD_NOT_ALLOWED));
        replay(request);
        replay(response);
        filter.doFilter(request, response, filterChain);
        verify(request);
        verify(response);
    }

    public void testConditionalGet() throws IOException, ServletException
    {
        final ImmortalFilter filter = new ImmortalFilter();
        final HttpServletRequest request = createMock(HttpServletRequest.class);
        final HttpServletResponse response = createMock(HttpServletResponse.class);
        final FilterChain filterChain = createMock(FilterChain.class);
        expect(request.getMethod()).andReturn("GET");
        expect(request.getDateHeader(eq(ImmortalFilter.IF_MODIFIED_SINCE_HEADER))).andReturn(100L);
        response.setStatus(eq(HttpServletResponse.SC_NOT_MODIFIED));
        expectCachingHeaders(response);
        replay(request);
        replay(response);
        filter.doFilter(request, response, filterChain);
        verify(request);
        verify(response);
    }

    public void testRegularRequest() throws IOException, ServletException
    {
        final ImmortalFilter filter = new ImmortalFilter();
        final HttpServletRequest request = createMock(HttpServletRequest.class);
        final HttpServletResponse response = createMock(HttpServletResponse.class);
        final FilterChain filterChain = createMock(FilterChain.class);
        expect(request.getMethod()).andReturn("GET");
        expect(request.getDateHeader(eq(ImmortalFilter.IF_MODIFIED_SINCE_HEADER))).andReturn(-1L);
        expect(request.getRequestURI()).andReturn("/resources/js/date.js");
        expectCachingHeaders(response);
        filterChain.doFilter(isA(HttpServletRequest.class), isA(HttpServletResponse.class));
        replay(request);
        replay(response);
        replay(filterChain);
        filter.doFilter(request, response, filterChain);
        verify(request);
        verify(response);
        verify(filterChain);
    }

    private static void expectCachingHeaders(HttpServletResponse mock)
    {
        mock.addDateHeader(eq(ImmortalFilter.EXPIRES_HEADER),
                geq(System.currentTimeMillis() + ImmortalFilter.ONE_YEAR_MILLISECS - 10000));
        mock.addHeader(eq(ImmortalFilter.CACHE_CONTROL_HEADER),
                eq(ImmortalFilter.CACHE_CONTROL_VALUE));
    }

    public void testETagHandler()
    {
        final HttpServletResponse response = createMock(HttpServletResponse.class);
        response.setHeader(eq(ImmortalFilter.CACHE_CONTROL_HEADER), eq(ImmortalFilter.CACHE_CONTROL_VALUE));
        replay(response);
        ImmortalFilter.ETagEvadingWrapper wrapper = new ImmortalFilter.ETagEvadingWrapper(response);
        wrapper.setHeader(ImmortalFilter.CACHE_CONTROL_HEADER, ImmortalFilter.CACHE_CONTROL_VALUE);
        wrapper.setHeader(ImmortalFilter.ETAG_HEADER, "XYZ");
        verify(response);
    }
}
